#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
logger = logging.getLogger('icon')

import clutter
from gstmanager.event import EventListener, EventLauncher
from buttons import ImageButton
from clutter import Label, Group, Color, Rectangle
import os, gobject

import touchwizard

class ActionIcon(EventLauncher, EventListener, Group):

    def __init__(self, file=None, launch_evt="default_action", listen_evt=None, desc="default_description", callback=None, cooldown_ms=100, action_args=None, ignore_lock_source=None, release_cb=None):
        EventLauncher.__init__(self)
        EventListener.__init__(self)

        self.registerEvent("lock_all")
        self.registerEvent("unlock_all")
        if listen_evt is not None:
            setattr(self, 'evt_%s' %listen_evt, lambda arg: self.animate())
            self.registerEvent(listen_evt)

        self.ignore_lock_source = ignore_lock_source

        self.launch_evt = launch_evt
        self.cooldown_ms = cooldown_ms
        self.is_locked = False
        self.action_args = action_args

        Group.__init__(self)
        self.set_anchor_point(0,0)
        filename = os.path.join(touchwizard.icons_path, "%s.png" %file)
        path=os.path.join(os.path.abspath(os.path.dirname(__file__)),filename)
        if callback is not None:
            self.callback = callback
            self.icon = icon = ImageButton(path=path, callback=self.action_cb, release_cb=release_cb)
        else:
            self.icon = icon = ImageButton(path=path, callback=self.action, release_cb=release_cb)

        self.label = label = Label()
        label.set_color(clutter.color_parse("Black"))
        label.set_font_name("Sans 12")
        label.set_text(desc)
        
        self.add(label)
        label.set_position((icon.get_width()-label.get_width())/2, 0)
        label.show()

        self.add(icon)
        icon.set_position(0, label.get_height())
        icon.show()

        do_visual_feedback = True
        self.do_visual_feedback = do_visual_feedback
        if do_visual_feedback:
            from candies.effects import OpacityEffect
            self.animation = OpacityEffect(
               duration=100, alphatype="ramp_inc", actor=self, looped=False
            )

    def get_height(self):
        height = int((self.icon.get_height()+self.label.get_height())*self.get_scale()[1])
        return height

    def get_width(self):
        width = int(float(self.icon.get_width())*float(self.get_scale()[0]))
        return width

    def action(self, *args):
        if not self.is_locked:
            self.lock_for(self.cooldown_ms)
            self.launchEvent(self.launch_evt, self.action_args)
        else:
            self.launchEvent("info", self.lock_info_msg)
            gobject.timeout_add(self.cooldown_ms, self.launchEvent, "info", "")
        self.animate()

    def evt_lock_all(self, event):
        if event.content["source"] not in [self, self.ignore_lock_source] and not self.ignore_lock_source == "any":
            self.lock(event.content["source"])

    def evt_unlock_all(self, event):
        if event.content["source"] not in [self, self.ignore_lock_source]:
            self.unlock()

    def lock(self, source=None):
        self.is_locked = True
        self.icon.set_opacity(80)
        if source is not None:
            self.lock_info_msg = "Please deactivate %s first" %source.label.get_text()
        else:
            self.lock_info_msg = "Please wait %ds" %(float(self.cooldown_ms/1000))

    def lock_for(self, duration):
        self.lock()
        gobject.timeout_add(duration, self.unlock)

    def unlock(self):
        self.is_locked = False
        self.icon.set_opacity(255)
        return False 

    def action_cb(self, *args):
        self.callback()
        self.animate()

    def animate(self):
        self.animation.run()

class ActionIconToggle(ActionIcon):
    def __init__(self, enabled=False, file_back=None, lock_others=False, **kwargs): 
        orig_evt = kwargs["launch_evt"]
        if file_back is not None:
            kwargs["launch_evt"] = "enable_%s" %orig_evt
        orig_desc = kwargs["desc"]
        kwargs["desc"] = "Enable %s" %orig_desc
        ActionIcon.__init__(self, **kwargs)
        try:
            self.lock_for(kwargs["cooldown_ms"])
        except Exception:
            pass

        deactive_evt = 'disabled_%s' %orig_evt
        setattr(self, "evt_%s" %deactive_evt, lambda arg: self.deactivate())
        self.registerEvent(deactive_evt)

        enabled_evt = 'enabled_%s' %orig_evt
        setattr(self, "evt_%s" %enabled_evt, lambda arg: self.activate())
        self.registerEvent(enabled_evt)

        self.lock_others = lock_others
        if file_back is None:
            self.back = back = Rectangle()
            back.set_size(*self.get_size())
            back.set_color(clutter.color_parse("Red"))
            self.dual_icon = False
        else:
            kwargs["launch_evt"] = "disable_%s" %orig_evt
            kwargs["file"] = file_back
            kwargs["desc"] = "Disable %s" %orig_desc
            if not "ignore_lock_source"in kwargs:
                self.back = back = ActionIcon(ignore_lock_source=self, **kwargs)
            else:
                self.back = back = ActionIcon(**kwargs)
            back.animate = self.animate
            self.dual_icon = True
        self.add(back)
        back.lower_bottom()
        if enabled:
            self.activate()

    def toggle_back(self):
        if not self.back.get_property("visible"):
            self.activate()
        else:
            self.deactivate()

    def deactivate(self):
        self.back.hide()
        if self.dual_icon:
            self.icon.show()
            self.label.show()
            self.lock_for(self.cooldown_ms)
        if self.lock_others:
            self.launchEvent("unlock_all", {"source": self})

    def activate(self):
        self.back.show()
        self.back.lock_for(self.cooldown_ms)
        if self.dual_icon:
            self.icon.hide()
            self.label.hide()
        if self.lock_others:
            self.launchEvent("lock_all", {"source": self})

    def animate(self):
        self.toggle_back()
        self.animation.run()

if __name__ == '__main__':
    import logging, sys

    logging.basicConfig(
        level=getattr(logging, "DEBUG"),
        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
        stream=sys.stderr
    )

    import candies
    from candies.core import Stage
    stage = Stage(640,480)
    t = ActionIcon(file="trash", launch_evt="enabled_test", desc="Enables")
    t2 = ActionIcon(file="trash", listen_evt="trash", desc="TrashListen")
    t3 = ActionIcon(file="trash", launch_evt="disabled_test", desc="Disables")
    t4 = ActionIconToggle(enabled=False, file="connect_established", file_back="connect_no", desc="Test", lock_others=True, launch_evt="test", cooldown_ms=2000)
    #t4 = ActionIconToggle(file="connect_established", file_back="connect_no", desc="Test", lock_others=True, launch_evt="test")
    t.show()
    t2.show()
    t3.show()
    t4.show()
    stage.add(t)
    stage.add(t2)
    stage.add(t3)
    stage.add(t4)
    t2.set_position(200, 0)
    t3.set_position(300, 0)
    t4.set_position(0, 200)
    stage.show()
    candies.main()
